<template>
    <div class="panel-wrap">
        <div class="phone-wrap">
            <div class="phone-all" ref="phoneAll" id="phoneAll">
                <img class="status-bar" src="@/assets/images/drag/phone_top.png" alt="" />
                <!-- 头部导航 -->
                <headerTop :pageSetup="pageSetup" @click.native="handleHeadTop" />
                <!-- 主体内容 -->
                <div
                    class="phone-container"
                    :style="{
                        'background-color': pageSetup.bgColor,
                        backgroundImage: 'url(' + pageSetup.bgImg + ')',
                    }"
                    @drop="handleDrop($event)"
                    @dragover="handleAllowDrop($event)"
                    @dragleave="handleDragleaves($event)"
                >
                    <div :class="pointer.show ? 'pointer-events' : ''">
                        <!-- 动态组件 -->

                        <template v-for="(item, index) in pageComponents">
                            <component
                                v-if="!preview.show"
                                :key="index"
                                :is="item.component"
                                :datas="item"
                                @click.native="handleActiveComponent(item, index)"
                                :class="['components-class', item.active && deleShow ? 'edit-seled' : '']"
                                :data-type="item.type"
                            >
                                <div v-show="deleShow" class="deles" slot="deles" @click.stop="handleDeleteCmp(index)">
                                    <!-- 删除组件 -->
                                    <span class="iconfont icon-sanjiaoxingzuo"></span>
                                    {{ item.text }}
                                    <i class="el-icon-delete-solid" />
                                </div>
                            </component>
                        </template>
                    </div>
                </div>
                <div v-show="pageComponents.length === 0" class="app-empty-tips">
                    <i class="el-icon-coin" style="font-size: 38px"></i>
                    {{ $t('drag.123456-59') }}
                </div>
                <!-- 手机高度 -->
                <div class="phoneSize">{{ $t('drag.123456-66') }}</div>
            </div>
        </div>
        <!-- 页面设置tab -->
        <div class="decorate-tab">
            <span :class="rightcom === 'decorate' ? 'active' : ''" @click="setRightcom('decorate')">
                <i class="iconfont icon-wangye" />
                {{ $t('drag.123456-6') }}
            </span>
            <span :class="rightcom === 'componenmanagement' ? 'active' : ''" @click="setRightcom('componenmanagement')">
                <i class="iconfont icon-zujian" />
                {{ $t('drag.123456-7') }}
            </span>
            <span class="active" v-if="rightcom != 'componenmanagement' && rightcom != 'decorate'">
                <i class="iconfont icon-zujian" />
                {{ $t('drag.123456-8') }}
            </span>
        </div>
        <realTimeView
            :datas="preview"
            :val="{
                id,
                name: pageSetup.name,
                templateJson: JSON.stringify(pageSetup),
                component: JSON.stringify(pageComponents),
            }"
        />
    </div>
</template>

<script>
import { mapState, mapActions } from 'vuex';
import html2canvas from 'html2canvas'; // 生成图片

import HeaderTop from './headerTop.vue';
import RealTimeView from './realTimeView.vue';
import utils from '@/utils/index'; // 方法类
import componentProperties from '@/utils/componentProperties'; // 组件数据

export default {
    name: 'PhonePanel',
    components: {
        HeaderTop,
        RealTimeView,
    },
    props: {
        preview: {
            show: false,
        },
        pointer: {
            show: false,
        },
    },
    computed: {
        ...mapState({
            rightcom: (state) => state.dragEditor.rightcom,
            pageSetup: (state) => state.dragEditor.pageSetup,
            pageComponents: (state) => state.dragEditor.pageComponents,
        }),
    },
    data() {
        return {
            id: null, //当前页面
            index: '', // 当前选中的index
            deleShow: true, //删除标签显示
            onlyOne: ['1-5', '1-16'], // 只能存在一个的组件(组件的type)
            offsetY: 0, // 记录上一次距离父元素高度
        };
    },
    mounted() {
        this.phoneAllDrag();
        this.phoneAllZoom();
    },
    methods: {
        ...mapActions('dragEditor', ['setPageComponents', 'setRightcom', 'setCurrentproperties']),
        // 监听整个手机的移动事件
        phoneAllDrag() {
            let isDragging = false; // 标记是否正在拖拽
            let x = 0,
                y = 0;
            const element = document.getElementById('phoneAll');
            element.addEventListener('mousedown', function (e) {
                isDragging = true; // 开始拖拽
                x = e.pageX - element.offsetLeft;
                y = e.pageY - element.offsetTop;
            });
            document.addEventListener('mousemove', function (e) {
                if (isDragging) {
                    let left = e.pageX - x;
                    let top = e.pageY - y;
                    element.style.left = left + 'px';
                    element.style.top = top + 'px';
                }
            });
            document.addEventListener('mouseup', function () {
                isDragging = false; // 结束拖拽
            });
        },
        // 通过滚轮进行缩放
        phoneAllZoom() {
            const element = document.getElementById('phoneAll');
            let scale = 1; // 初始缩放比例
            const zoomSpeed = 0.1; // 缩放速度
            element.addEventListener('wheel', function (event) {
                event.preventDefault();
                const deltaY = event.deltaY;
                const direction = deltaY > 0 ? -1 : 1; // 判断滚轮方向（向下为缩小，向上为放大）
                scale += direction * zoomSpeed; // 更新缩放比例
                scale = Math.max(0.6, Math.min(scale, 1.4)); // 限制缩放范围
                element.style.transform = `scale(${scale})`; // 应用缩放效果
            });
        },
        // 放置目标元素上或选择文本时触发此事件
        handleDrop(event) {
            let data = utils.deepClone(componentProperties.get(event.dataTransfer.getData('componentName')));
            // 查询是否只能存在一个的组件且在第一个
            let someOne = this.pageComponents.some((item, index) => {
                return item.component === 'placementarea' && index === 0 && this.onlyOne.includes(data.type);
            });
            if (someOne) {
                this.$message.info('固定位置的组件(如: 底部导航、悬浮)不能放在第一个!');
                this.handleDragleaves();
                return;
            }
            let someResult = this.pageComponents.some((item) => {
                return this.onlyOne.includes(item.type) && item.component === event.dataTransfer.getData('componentName');
            });
            if (someResult) {
                this.$message.info('当前组件只能添加一个!');
                // 删除提示组件
                this.handleDragleaves();
                return;
            }
            utils.forEach(this.pageComponents, (res, index) => {
                if (res.active === true) res.active = false;
                this.index = index;
                if (res.component === 'placementarea') {
                    const list = this.pageComponents.map((item, i) => {
                        if (i === index) {
                            return data;
                        }
                        return item;
                    });
                    this.setPageComponents(list);
                }
            });
            this.setRightcom(data.style); // 切换组件
            this.setCurrentproperties(data); // 丢样式
        },
        // 当将元素或文本选择拖动到有效放置目标（每几百毫秒）上时，会触发此事件
        handleAllowDrop(event) {
            event.preventDefault();
            // 获取鼠标高度
            let eventoffset = event.offsetY;
            if (this.offsetY === eventoffset) return;
            else this.offsetY = eventoffset;
            const childrenObject = event.target.children[0];
            if (!childrenObject) return;
            // 一个以上的组件计算
            if (this.pageComponents.length) {
                /* 如果只有一个组件并且第一个是提示组件直接返回 */
                if (this.pageComponents.length === 1 && this.pageComponents[0].type === 0) return;
                /* 如果鼠标的高度小于第一个的一半直接放到第一个 */
                if (childrenObject.children[0] && eventoffset < childrenObject.children[0].clientHeight / 2) {
                    /* 如果第一个是提示组件直接返回 */
                    if (this.pageComponents[0].type === 0) return;
                    /* 删除提示组件 */
                    let list = this.pageComponents.filter((res) => res.component !== 'placementarea') || [];
                    /* 最后面添加提示组件 */
                    list.unshift({
                        component: 'placementarea',
                        type: 0,
                    });
                    this.setPageComponents(list);
                    return;
                }
                /* 记录距离父元素高度 */
                const childOff = childrenObject.offsetTop;
                /* 鼠标在所有组件下面 */
                if (eventoffset > childrenObject.clientHeight || childrenObject.lastChild.offsetTop - childOff + childrenObject.lastChild.clientHeight / 2 < eventoffset) {
                    if (this.pageComponents[this.pageComponents.length - 1].type === 0) return;
                    let list = this.pageComponents.filter((res) => res.component !== 'placementarea') || [];
                    list.push({
                        component: 'placementarea',
                        type: 0,
                    });
                    this.setPageComponents(list);
                    return;
                }
                const childrens = childrenObject.children;
                // 在两个组件中间，插入
                for (let i = 0, l = childrens.length; i < l; i++) {
                    const childoffset = childrens[i].offsetTop - childOff;
                    if (childoffset + childrens[i].clientHeight / 2 > event.offsetY) {
                        /* 如果是提示组件直接返回 */
                        if (this.pageComponents[i].type === 0) break;
                        if (this.pageComponents[i - 1].type === 0) break;
                        /* 清除提示组件 */
                        let list = this.pageComponents.filter((res) => res.component !== 'placementarea') || [];
                        list.splice(i, 0, {
                            component: 'placementarea',
                            type: 0,
                        });
                        this.setPageComponents(list);
                        break;
                    } else if (childoffset + childrens[i].clientHeight > event.offsetY) {
                        if (this.pageComponents[i].type === 0) break;
                        if (!this.pageComponents[i + 1] || this.pageComponents[i + 1].type === 0) break;
                        let list = this.pageComponents.filter((res) => res.component !== 'placementarea') || [];
                        list.splice(i, 0, {
                            component: 'placementarea',
                            type: 0,
                        });
                        this.setPageComponents(list);
                        break;
                    }
                }
            } else {
                // 一个组件都没有直接push
                let list = [...this.pageComponents];
                list.push({
                    component: 'placementarea',
                    type: 0,
                });
                this.setPageComponents(list);
            }
        },
        // 当拖动的元素或文本选择离开有效的放置目标时，会触发此事件
        handleDragleaves() {
            const list = this.pageComponents.filter((res) => res.component !== 'placementarea');
            this.setPageComponents(list);
        },
        // 删除组件
        handleDeleteCmp(index) {
            this.pageComponents.splice(index, 1);
            if (this.index === index) this.setRightcom('decorate');
            if (index < this.index) this.index = this.index - 1;
        },
        // 选择组件
        handleActiveComponent(res, index) {
            this.index = index;
            this.setRightcom(res.style);
            this.setCurrentproperties(res);
            /* 替换 */
            utils.forEach(this.pageComponents, (res) => {
                if (res.active === true) res.active = false;
            });
            res.active = true; // 选中样式
        },
        // 标题切换
        handleHeadTop() {
            this.setRightcom('decorate');
            /* 替换 */
            utils.forEach(this.pageComponents, (res) => {
                if (res.active === true) res.active = false;
            });
        },
        // 保存
        handlePreservation() {
            this.deleShow = false;
            this.$nextTick(() => {
                this.toImage();
            });
        },
        // 页面截图
        toImage() {
            const loading = this.$loading({
                lock: true,
                text: '保存中...',
                spinner: 'el-icon-loading',
                background: 'rgba(0, 0, 0, 0.7)',
            });
            const imageTofiles = document.querySelector('#phoneAll');
            html2canvas(this.$refs.phoneAll, {
                backgroundColor: null,
                height: imageTofiles.scrollHeight,
                width: imageTofiles.scrollWidth,
                useCORS: true,
            }).then((canvas) => {
                /* 显示border和删除图标 */
                this.deleShow = true;
                let url = canvas.toDataURL('image/png');
                const formData = new FormData();
                formData.append('base64File', url);
                console.log(formData, '--------------页面图片formData');
                loading.close();
            });
        },
    },
};
</script>

<style lang="scss" scoped>
.panel-wrap {
    width: 100%;
    height: 100%;
    position: relative;

    .phone-wrap {
        width: 100%;
        height: 100%;
        overflow-y: scroll;
        display: flex;
        justify-content: center;
        background: #f7f8fa;
        position: relative;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;

        &::-webkit-scrollbar {
            width: 0px;
        }

        /* 手机样式 */
        .phone-all {
            display: flex;
            flex-direction: column;
            width: 375px;
            min-height: 660px;
            box-shadow: 0 0 14px 0 rgba(0, 0, 0, 0.1);
            position: absolute;

            /* 手机高度 */
            .phoneSize {
                position: absolute;
                left: -137px;
                top: 640px;
                font-size: 12px;
                color: #a2a2a2;
                border-bottom: 1px solid #dedede;
                width: 130px;
                height: 21px;
                line-height: 21px;
            }

            /* 状态栏 */
            .status-bar {
                width: 100%;
                display: block;
            }

            /* 主体内容 */
            .phone-container {
                flex: 1;
                box-sizing: border-box;
                cursor: pointer;
                width: 100%;
                position: relative;
                background-repeat: no-repeat;
                background-size: cover;
                background-position: center center;

                .pointer-events {
                    pointer-events: none;
                }

                .components-class {
                    border: 1px solid transparent;
                    &:hover {
                        border: 1px dashed #155bd4c4;
                    }
                }

                .edit-seled {
                    outline: 2px dashed #155bd4c4;
                    outline-offset: -1px;
                    z-index: 1;
                }
            }

            .app-empty-tips {
                display: flex;
                flex-direction: column;
                align-items: center;
                gap: 20px;
                color: #c0c4cc;
                font-size: 16px;
                position: absolute;
                top: 200px;
                left: 0;
                right: 0;
            }
        }
    }

    // 删除组件
    .deles {
        position: absolute;
        min-width: 80px;
        text-align: center;
        line-height: 25px;
        background: #fff;
        height: 25px;
        font-size: 12px;
        left: 103%;
        top: 50%;
        transform: translateY(-50%);

        .icon-sanjiaoxingzuo {
            position: absolute;
            left: -11px;
            color: #fff;
            font-size: 12px;
            top: 50%;
            transform: translateY(-50%);
        }

        &:hover {
            i {
                display: block;
                position: absolute;
                left: 0;
                font-size: 16px;
                top: 0;
                text-align: center;
                line-height: 25px;
                width: 100%;
                color: #fff;
                height: 100%;
                z-index: 10;
                background: rgba(0, 0, 0, 0.5);
            }
            .icon-sanjiaoxingzuo {
                color: rgba(0, 0, 0, 0.5);
            }
        }

        i {
            display: none;
        }
    }

    .decorate-tab {
        position: absolute;
        display: flex;
        right: 0;
        top: 0px;
        flex-direction: column;

        span {
            background-color: #fff;
            width: 94px;
            height: 36px;
            display: inline-block;
            text-align: center;
            line-height: 36px;
            transition: all 0.8s;
            cursor: pointer;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;

            &:not(:last-child) {
                border-bottom: 1px solid #f2f4f6;
            }

            &.active {
                color: #155bd4;
            }
            /* 图标 */
            i {
                font-size: 12px;
                margin-right: 5px;
            }
        }
    }
}
</style>
